home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Plus 2004 #9
/
Amiga Plus CD - 2004 - No. 09.iso
/
amigaplus
/
tools
/
amigaos4_only
/
fracblank
/
source
/
fraccontrol.c
< prev
next >
Wrap
C/C++ Source or Header
|
2004-08-03
|
10KB
|
322 lines
/*
** FracBlank - AmigaDOS 2.04 commodities utility screenblanker
**
** Copyright © 1991-1995 by Olaf `Olsen' Barthel
** All Rights Reserved
**
** Cosmic flame fractal code derived from xlock source code
**
** Copyright © 1988-1991 by Patrick J. Naughton.
*/
#include <math.h>
#include <proto/dos.h>
#include <proto/exec.h>
#include <proto/graphics.h>
#include <proto/intuition.h>
#include "Frac.h"
#include "FracControl.h"
// BlankerEntry data
ULONG Pen;
WORD Width,
Height;
struct Task *BlankTask;
struct Screen *BlankScreen;
struct Window *BlankWindow;
struct RastPort *RPort;
struct ViewPort *VPort;
// In case we need to rescale things
double VerticalScale;
// Colour table data
UBYTE Red[255],
Green[255],
Blue[255];
WORD MaxColour,
Wheel;
ColourTable *Colours;
// Some kind of a semaphore to tell the blank task to stop drawing
BYTE StopDrawing = FALSE;
// Prototypes
void hsvramp(double h1, double s1, double b1, double h2, double s2, double b2, int count, UBYTE *red, UBYTE *green, UBYTE *blue);
void hsv2rgb(double H, double S, double V, UBYTE *r, UBYTE *g, UBYTE *b);
/* BlankerControlEntry():
*
* The screen blanker control task.
*/
VOID BlankerControlEntry() {
ULONG SignalSet;
IExec->Forbid();
// Ring back...
IExec->Signal((struct Task *)MainProcess,SIG_HANDSHAKE);
for(;;) {
// Wait for something to happen
SignalSet = IExec->Wait(SIG_BREAK | SIG_START | SIG_CHANGE | SIG_FINISH);
// Remove both the screen and the blanker task?
if (SignalSet & (SIG_BREAK | SIG_FINISH)) {
IExec->ObtainSemaphore(&BlankSemaphore);
if (BlankScreen) IIntuition->ScreenToBack(BlankScreen);
// Remove the blanker task
if (BlankTask) {
IExec->SetSignal(0,SIG_HANDSHAKE);
// Tell the blanker task to shut down
IExec->Signal(BlankTask,SIG_BREAK);
// Move the blanker task priority up,
// we don't want the low priority task
// to wait until some high priority task
// yields CPU time
IExec->SetTaskPri(BlankTask,127);
// Wait for handshake signal...
IExec->Wait(SIG_HANDSHAKE);
// He's dead, Jim
BlankTask = NULL;
}
// Close the blanker screen
if (BlankScreen) {
IIntuition->ScreenToBack(BlankScreen);
IIntuition->CloseWindow(BlankWindow);
BlankWindow = NULL;
IIntuition->CloseScreen(BlankScreen);
BlankScreen = NULL;
}
IExec->ReleaseSemaphore(&BlankSemaphore);
SignalSet &= ~(SIG_CHANGE | SIG_START);
}
// Leave the town?
if (SignalSet & SIG_FINISH) break;
// Start the screen blanker?
if (SignalSet & SIG_START) {
// Is the screen already open?
if (!BlankScreen) {
ULONG LocalID;
// Use the default public screen display ID
// if necessary
if (DisplayID == INVALID_ID || (IGraphics->ModeNotAvailable(DisplayID) & ~DI_AVAIL_NOTWITHGENLOCK)) {
struct Screen *PubScreen = IIntuition->LockPubScreen(NULL);
if (PubScreen) {
LocalID = IGraphics->GetVPModeID(&PubScreen->ViewPort);
IIntuition->UnlockPubScreen(NULL,PubScreen);
}
else LocalID = INVALID_ID;
}
else LocalID = DisplayID;
// Did we get a valid ID?
if (LocalID != INVALID_ID) {
WORD LocalDepth;
struct DimensionInfo DimensionInfo;
struct DisplayInfo DisplayInfo;
// Choose the right display depth
LocalDepth = Depth;
if (IGraphics->GetDisplayInfoData(NULL,(APTR)&DimensionInfo,sizeof(DimensionInfo),DTAG_DIMS,LocalID)) {
if (!LocalDepth) {
if ((LocalDepth = DimensionInfo.MaxDepth) > 8) LocalDepth = 8;
}
else {
if (LocalDepth > DimensionInfo.MaxDepth) LocalDepth = DimensionInfo.MaxDepth;
}
}
else {
if (!LocalDepth) LocalDepth = 2;
}
// Compensate for the display aspect ratio
if (IGraphics->GetDisplayInfoData(NULL,(APTR)&DisplayInfo,sizeof(DisplayInfo),DTAG_DISP,LocalID)) {
if (DisplayInfo.Resolution.y) {
double x,y;
x = (double)DisplayInfo.Resolution.x;
y = (double)DisplayInfo.Resolution.y;
VerticalScale = x / y;
}
else VerticalScale = 1.0;
}
else VerticalScale = 1.0;
// Set the colour table to black
MaxColour = (1 << LocalDepth) - 1;
Colours->NumColours = MaxColour + 1;
memset(&Colours->Entry[0],0,256 * sizeof(ColourEntry));
// Now open the screen and the window
IExec->ObtainSemaphore(&BlankSemaphore);
if (BlankScreen = IIntuition->OpenScreenTags(NULL,
SA_Behind, TRUE,
SA_Quiet, TRUE,
SA_DisplayID, LocalID,
SA_Overscan, OSCAN_MAX,
SA_Depth, LocalDepth,
SA_ShowTitle, FALSE,
SA_BackFill, &ScreenHook,
SA_Colors32, Colours,
SA_Draggable, FALSE,
SA_Exclusive, TRUE,
TAG_DONE)) {
VPort = &BlankScreen->ViewPort;
Width = BlankScreen->Width;
Height = BlankScreen->Height;
// To keep the ball rolling...
if ((DisplayDepth = LocalDepth) == 1) {
MaxColour = 255;
Colours->NumColours = 2;
}
// Create a nice colour table
hsvramp(0.0,1.0,1.0,1.0,1.0,1.0,MaxColour,Red,Green,Blue);
Wheel = Random(MaxColour);
RotatePalette();
// Open the window
if (BlankWindow = IIntuition->OpenWindowTags(NULL,
WA_Left, 0,
WA_Top, 0,
WA_Width, Width,
WA_Height, Height,
WA_Backdrop, TRUE,
WA_Borderless, TRUE,
WA_Pointer, Pointer,
WA_CustomScreen, BlankScreen,
WA_Activate, TRUE,
WA_RMBTrap, TRUE,
WA_BackFill, &WindowHook,
TAG_DONE)) {
RPort = BlankWindow->RPort;
IGraphics->SetABPenDrMd(RPort,Pen = 1,0,JAM1);
// Clear the screen
IGraphics->SetRast(RPort,0);
IGraphics->LoadRGB32(VPort,(ULONG *)Colours);
// Display the screen
IIntuition->ScreenToFront(BlankScreen);
PatternCount = 0;
// Wait for something to happen
IExec->Forbid();
BlankTask = (struct Task *)IExec->CreateTask("« FracBlank BlankerEntry Task »",127,BlankerEntry,16384 + 400 * MaxRecursionLevel,NULL);
IExec->SetSignal(0,SIG_HANDSHAKE);
IExec->Wait(SIG_HANDSHAKE);
IExec->Permit();
}
else {
IIntuition->CloseScreen(BlankScreen);
BlankScreen = NULL;
}
}
}
IExec->ReleaseSemaphore(&BlankSemaphore);
}
else {
// Push the blanker screen to the front if necessary
if (BlankScreen->TopEdge > 0) IIntuition->MoveScreen(BlankScreen,0,-BlankScreen->TopEdge);
if (IntuitionBase->FirstScreen != BlankScreen) IIntuition->ScreenToFront(BlankScreen);
if (IntuitionBase->ActiveWindow != BlankWindow) IIntuition->ActivateWindow(BlankWindow);
}
SignalSet &= ~SIG_CHANGE;
}
// Change the patterns?
if (SignalSet & SIG_CHANGE) {
if (BlankTask) {
// Stop drawing patterns
StopDrawing = TRUE;
IExec->Signal(BlankTask,SIG_CHANGE);
}
}
}
BlankerControlProcess = NULL;
IExec->Signal((struct Task *)MainProcess,SIG_HANDSHAKE);
}
/* hsvramp():
*
* Creates a ramp within HSV colour space, showing all
* colours of the HSV circle.
*/
void hsvramp(double h1, double s1, double b1, double h2, double s2, double b2, int count, UBYTE *red, UBYTE *green, UBYTE *blue) {
double dh,ds,db;
dh = (h2 - h1) / count;
ds = (s2 - s1) / count;
db = (b2 - b1) / count;
while(count--) {
hsv2rgb(h1,s1,b1,red++,green++,blue++);
h1 += dh;
s1 += ds;
b1 += db;
}
}
/* hsv2rgb(double H,double S,double V,UBYTE *r,UBYTE *g,UBYTE *b):
*
* Convert HSV (hue, saturation, value) colour index into
* plain RGB (red, green, blue) colour space.
*/
void hsv2rgb(double H, double S, double V, UBYTE *r, UBYTE *g, UBYTE *b) {
int i;
double f,
bb;
UBYTE p,
q,
t;
H -= floor(H);
H *= 6.0;
i = floor(H);
f = H - (double)i;
bb = 255.0 * V;
p = (UBYTE)(bb * (1.0 - S));
q = (UBYTE)(bb * (1.0 - (S * f)));
t = (UBYTE)(bb * (1.0 - (S * (1.0 - f))));
switch(i) {
case 0: *r = (UBYTE)bb;
*g = t;
*b = p;
break;
case 1: *r = q;
*g = (UBYTE)bb;
*b = p;
break;
case 2: *r = p;
*g = (UBYTE)bb;
*b = t;
break;
case 3: *r = p;
*g = q;
*b = (UBYTE)bb;
break;
case 4: *r = t;
*g = p;
*b = (UBYTE)bb;
break;
case 5: *r = (UBYTE)bb;
*g = p;
*b = q;
break;
}
}